﻿Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports Spring.Transaction
Imports Spring.Transaction.Support
Imports System.IO

''' <summary>
''' Esta classe é um porte da classe AbstractTransactionalSpringContextTests do Spring.
''' Foi adaptada para usar o framework de teste da M$.
''' Esta classe inicia uma transacao a cada método de teste sendo executado, e ao final do método faz o Rollback.
''' Caso queira dar um commit, deve-se chamar o método SetComplete() para commitar. Leia a documentação da classe AbstractTransactionalSpringContextTests para mais informações.
''' </summary>
''' <remarks></remarks>
Public MustInherit Class TesteTransacionalInjecaoDependenciaSpring
    Inherits TesteInjecaoDependenciaSpring

    ''' <summary>
    ''' The transaction manager to use
    ''' </summary>
    Protected _transactionManager As IPlatformTransactionManager

    ''' <summary>
    ''' Should we roll back by default?
    ''' </summary>
    Private _defaultRollback As Boolean = True

    ''' <summary>
    ''' Should we commit the current transaction?
    ''' </summary>
    Private _complete As Boolean = False

    ''' <summary>
    ''' Number of transactions started
    ''' </summary>
    Private _transactionsStarted As Integer = 0

    ''' <summary>
    ''' Default transaction definition is used.
    ''' Subclasses can change this to cause different behaviour.
    ''' </summary>
    Private _transactionDefinition As ITransactionDefinition = New DefaultTransactionDefinition()

    ''' <summary>
    ''' TransactionStatus for this test. Typical subclasses won't need to use it.
    ''' </summary>
    Protected _transactionStatus As ITransactionStatus


    ''' <summary>
    ''' Initializes a new instance of the <see cref="TesteTransacionalInjecaoDependenciaSpring"/> class.
    ''' </summary>
    Public Sub New()
    End Sub

    ''' <summary>
    ''' Sets the transaction manager to use.
    ''' </summary>
    Public WriteOnly Property TransactionManager() As IPlatformTransactionManager
        Set(ByVal value As IPlatformTransactionManager)
            _transactionManager = value
        End Set
    End Property

    ''' <summary>
    ''' Sets the default rollback flag.
    ''' </summary>
    Public WriteOnly Property DefaultRollback() As Boolean
        Set(ByVal value As Boolean)
            _defaultRollback = value
        End Set
    End Property

    ''' <summary>
    ''' Set the <see cref="ITransactionDefinition"/> to be used
    ''' </summary>
    ''' <remarks>
    ''' Defaults to <see cref="DefaultTransactionDefinition"/>
    ''' </remarks>
    Protected WriteOnly Property TransactionDefinition() As ITransactionDefinition
        Set(ByVal value As ITransactionDefinition)
            _transactionDefinition = value
        End Set
    End Property

    ''' <summary>
    ''' Prevents the transaction.
    ''' </summary>
    Protected Overridable Sub PreventTransaction()
        Me._transactionDefinition = Nothing
    End Sub


    ''' <summary>
    ''' Creates a transaction
    ''' </summary>
    <TestInitialize()> _
    Public Overloads Overrides Sub Initialize()
        MyBase.Initialize()
        Me._complete = Not Me._defaultRollback

        If Me._transactionManager Is Nothing Then
            logger.Info("No transaction manager set: test will NOT run within a transaction")
            System.Diagnostics.Trace.WriteLine("No transaction manager set: test will NOT run within a transaction")
        ElseIf Me._transactionDefinition Is Nothing Then
            System.Diagnostics.Trace.WriteLine("No transaction definition set: test will NOT run within a transaction")
            logger.Info("No transaction definition set: test will NOT run within a transaction")
        Else
            OnSetUpBeforeTransaction()
            StartNewTransaction()
            Try
                OnSetUpInTransaction()
            Catch generatedExceptionName As Exception
                EndTransaction()
                Throw
            End Try
        End If
    End Sub


    ''' <summary>
    ''' Callback method called before transaction is setup.
    ''' </summary>
    Protected Overridable Sub OnSetUpBeforeTransaction()
    End Sub

    ''' <summary>
    ''' Callback method called after transaction is setup.
    ''' </summary>
    Protected Overridable Sub OnSetUpInTransaction()
    End Sub

    ''' <summary>
    ''' rollback the transaction.
    ''' </summary>
    <TestCleanup()> _
    Public Overloads Overrides Sub Finnalize()
        MyBase.Finnalize()
        ' Call onTearDownInTransaction and end transaction if the transaction is still active.
        If Not Me._transactionStatus Is Nothing AndAlso Not Me._transactionStatus.Completed Then
            Try
                OnTearDownInTransaction()
            Finally
                EndTransaction()
            End Try
        End If
        ' Call onTearDownAfterTransaction if there was at least one transaction,
        ' even if it has been completed early through an endTransaction() call.
        If Me._transactionsStarted > 0 Then
            OnTearDownAfterTransaction()
        End If
    End Sub

    ''' <summary>
    ''' Callback before rolling back the transaction.
    ''' </summary>
    Protected Overridable Sub OnTearDownInTransaction()
    End Sub

    ''' <summary>
    ''' Callback after rolling back the transaction.
    ''' </summary>
    Protected Overridable Sub OnTearDownAfterTransaction()
    End Sub

    ''' <summary>
    ''' Set the complete flag..
    ''' </summary>
    Protected Overridable Sub SetComplete()
        If Me._transactionManager Is Nothing Then
            Throw New InvalidOperationException("No transaction manager set")
        End If
        Me._complete = True
    End Sub

    ''' <summary>
    ''' Ends the transaction.
    ''' </summary>
    Protected Overridable Sub EndTransaction()
        If Not Me._transactionStatus Is Nothing Then
            Try
                If Not Me._complete Then
                    Me._transactionManager.Rollback(Me._transactionStatus)
                    System.Diagnostics.Trace.WriteLine("Rolled back transaction after test execution")
                    logger.Info("Rolled back transaction after test execution")
                Else
                    Me._transactionManager.Commit(Me._transactionStatus)
                    System.Diagnostics.Trace.WriteLine("Committed transaction after test execution")
                    logger.Info("Committed transaction after test execution")
                End If
            Finally
                Me._transactionStatus = Nothing
            End Try
        End If
    End Sub

    ''' <summary>
    ''' Starts the new transaction.
    ''' </summary>
    Protected Sub StartNewTransaction()
        If Not Me._transactionStatus Is Nothing Then
            Throw New InvalidOperationException("Cannot start new transaction without ending existing transaction: " + "Invoke endTransaction() before startNewTransaction()")
        End If
        If Me._transactionManager Is Nothing Then
            Throw New InvalidOperationException("No transaction manager set")
        End If

        Me._transactionStatus = Me._transactionManager.GetTransaction(Me._transactionDefinition)
        System.Threading.Interlocked.Increment(Me._transactionsStarted)
        Me._complete = Not Me._defaultRollback

        If logger.IsInfoEnabled Then
            System.Diagnostics.Trace.WriteLine("Began transaction (" & Me._transactionsStarted.ToString() & "): transaction manager [" & Me._transactionManager.ToString() & "]; default rollback = " & Me._defaultRollback.ToString())
            logger.Info("Began transaction (" & Me._transactionsStarted.ToString() & "): transaction manager [" & Me._transactionManager.ToString() & "]; default rollback = " & Me._defaultRollback.ToString())
        End If
    End Sub


    <ClassInitialize()> Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)

        'Dim _testRun As TestRun
        'Dim _arquivos() As String
        'Try
        '    _arquivos = Directory.GetFiles("C:\projetos\TestResults\")

        '    For Each _arquivo In _arquivos
        '        Try
        '            _testRun = TRXSerializer.DESSerialize(_arquivo)
        '            TRXLogger.Log(_testRun)
        '        Catch ex As Exception
        '            Console.WriteLine(ex.Message)
        '        End Try
        '    Next
        'Catch ex As Exception
        '    Console.WriteLine(ex.Message)
        'End Try

    End Sub


End Class
'End Namespace